#include "commandworker.h"
#include <QMessageBox>
#include <QAbstractButton>

CommandWorker::CommandWorker(QObject *parent) :QObject(parent)
{
    m_serialPort=new QSerialPort(this);
    m_timeoutTimer=new QTimer(this);
    m_timeoutTimer->setSingleShot(true);
    connect(m_serialPort,&QSerialPort::readyRead,this,&CommandWorker::HandleReadyRead);
    connect(m_timeoutTimer,&QTimer::timeout,this,&CommandWorker::HandleTimeout);
}


void CommandWorker::start(const QList<QByteArray> &commands)
{
    m_serialPort->setPortName(Utils::m_portName);
    m_serialPort->setBaudRate(Utils::instance()->getSerialBaudRate());
    m_serialPort->setDataBits(Utils::instance()->getSerialPortDataBits());
    m_serialPort->setParity(Utils::instance()->getSerialPortParity());
    m_serialPort->setStopBits(Utils::instance()->getSerialPortStopBits());
    m_timeout=Utils::instance()->getTimeOutMs();
    if (!m_serialPort->open(QIODevice::ReadWrite))
    {
        emit openFailed(m_serialPort->errorString());
        emit allTaskFinished();  // 发信号，告诉外面
        return;
    }
    m_commandQueue.clear();
    for(const QByteArray& command: commands)
    {
        m_commandQueue.enqueue(command);
    }
    //发送一个命令
    sendNextCommand();
}

void CommandWorker::logCommandResponse(const QByteArray &command, const QByteArray &response, const QString &sendTime, const QString &receiveTime, int responseTime, const QString &status)
{
    QString text_rsptime;
    QString text_status;

    if(status=="错误")
    {
        text_rsptime="响应时间："+QString::number(responseTime);
        text_status="<font color='red'>电表应答："+status+"</font>";
    }
    else if(status=="超时")
    {
        text_rsptime="<font color='red'>响应时间："+QString::number(responseTime)+"</font>";
        text_status="<font color='red'>电表应答："+status+"</font>";
    }
    else
    {
        text_rsptime="响应时间："+QString::number(responseTime);
        text_status="电表应答："+status;
    }
    QString log=QString("-&gt;%1<br>&lt;%2<br>发送时刻：%3<br>接收时刻：%4<br>%5<br>%6<br>")
            .arg(QString(command.toHex(' ').toUpper()))
            .arg(QString(response.toHex(' ').toUpper()))
            .arg(sendTime)
            .arg(receiveTime)
            .arg(text_rsptime)
            .arg(text_status);
    emit OneFrameFinished(log);
}

void CommandWorker::HandleReadyRead()
{
//    QString status="正常";
//    QByteArray response=m_serialPort->readAll();
//    //获取当前时间
//    QString receiveTime=QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
//    //计算响应时间
//    int responseTime=m_sendTime.msecsTo(QDateTime::currentDateTime());
//    if((response.size()<(Utils::LEN+1+4)) || (response.size()!=(Utils::Frame::LEN+response.at(Utils::Frame::LEN)+2+1)))
//    {
//        status="错误";
//    }
//    //记录发送命令与接收应答的信息
//    logCommandResponse(m_currentCommand,response,m_sendTime.toString("yyyy-MM-dd HH:mm:ss.zzz"),
//                       receiveTime,responseTime,status);
//    //发送下一个命令
//    sendNextCommand();

    m_receivedData.append(m_serialPort->readAll());
    //判断是否接收完整一帧
    if(m_receivedData.size()>=((Utils::Frame::LEN)+1+4))
    {
        int expectedLength=4+(Utils::Frame::LEN)+static_cast<unsigned char>(m_receivedData.at(4+(Utils::Frame::LEN)))+1+2;
        if(m_receivedData.size()>=expectedLength)
        {
            //收到完整一帧
            m_timeoutTimer->stop();
            QString status;
            QString receiveTime=QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
            int responseTime=m_sendTime.msecsTo(QDateTime::currentDateTime());
            status=CheckFrame(m_receivedData);
            if(Utils::instance()->isSub33()==true)
            {
                Utils::Framesub33(m_receivedData);
            }
            logCommandResponse(m_currentCommand,m_receivedData,m_sendTime.toString("yyyy-MM-dd HH:mm:ss.zz"),
                                    QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz"),responseTime,status);
            emit commandResult(m_receivedData);
            //发送下一个命令
            sendNextCommand();
        }
    }

}

void CommandWorker::sendNextCommand()
{
    if(m_commandQueue.isEmpty())
    {
        m_serialPort->close();
        emit allTaskFinished();
        //deleteLater();
        return;
    }
    //获取队列中下一个命令
    m_currentCommand=m_commandQueue.dequeue();
    //记录发送时刻
    m_sendTime=QDateTime::currentDateTime();
    //清除接收缓冲区
    m_receivedData.clear();
    //发送命令帧
    m_serialPort->write(m_currentCommand);
    //设置超时等待应答
    m_timeoutTimer->start(m_timeout);
}

void CommandWorker::HandleTimeout()
{
    //超时处理：未收到应答
    QString receiveTime=QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
    int responseTime=m_sendTime.msecsTo(QDateTime::currentDateTime());

    //记录信息
//    emit CommandResponse(m_currentCommand,"",m_sendTime,QDateTime::currentDateTime());
//    emit CommandStatus("超时");
    logCommandResponse(m_currentCommand,"",m_sendTime.toString("yyyy-MM-dd HH:mm:ss.zzz"),receiveTime,responseTime,"超时");
    //继续发送下一个命令
    sendNextCommand();
}

QString CommandWorker::CheckFrame(QByteArray arr)
{
    if(arr.size()<(4+Utils::Frame::DI0) || arr.size()!=(4+Utils::Frame::DI0+arr.at(4+Utils::Frame::LEN)+2))
    {
        return "错误";
    }
    unsigned char cmd=arr.at(4+Utils::CMD);
    if( (cmd>0xD0 && cmd<<0xDD) || cmd==0xC3)
    {
        return "错误";
    }
    quint8 sum = 0;
    for (int i = 4; i < 4+Utils::Frame::DI0+arr.at(4+Utils::Frame::LEN); ++i) {
        sum += static_cast<quint8>(arr[i]);
    }
    if((quint8)arr.at(arr.size()-2) !=sum)
    {
        return "错误";
    }
    return "正常";
}
